#***************************************************************************
#                                  _   _ ____  _
#  Project                     ___| | | |  _ \| |
#                             / __| | | | |_) | |
#                            | (__| |_| |  _ <| |___
#                             \___|\___/|_| \_\_____|
#
# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at https://curl.se/docs/copyright.html.
#
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
# copies of the Software, and permit persons to whom the Software is
# furnished to do so, under the terms of the COPYING file.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
# SPDX-License-Identifier: curl
#
###########################################################################
# 查找系统中的 nghttpx 程序，将其路径存储在 TEST_NGHTTPX 变量中
find_program(TEST_NGHTTPX "nghttpx")
# 若未找到 nghttpx 程序，则将 TEST_NGHTTPX 设置为 "nghttpx"
if(NOT TEST_NGHTTPX)
  set(TEST_NGHTTPX "nghttpx")
endif()
# 将 TEST_NGHTTPX 变量标记为高级变量，在 CMake GUI 中默认隐藏
mark_as_advanced(TEST_NGHTTPX)
# 根据 config.in 模板文件生成 config 文件，将 TEST_NGHTTPX 变量的值填充进去
# 此操作会使用 @ONLY 模式，仅替换 @VAR@ 形式的变量
# Consumed variables: TEST_NGHTTPX
configure_file("config.in" "${CMAKE_CURRENT_BINARY_DIR}/config" @ONLY)

# 创建一个名为 testdeps 的自定义目标，用于作为其他测试目标的依赖项
add_custom_target(testdeps)
# 添加子目录，这些子目录包含测试相关的代码和配置
add_subdirectory(http)
add_subdirectory(http/clients)
add_subdirectory(server)
add_subdirectory(libtest)
add_subdirectory(unit)
add_subdirectory(certs)

# 定义一个函数，用于添加运行测试的自定义目标
function(curl_add_runtests _targetname _test_flags)
  # 若未构建 libcurl 文档，则在测试标志中添加 !documentation，跳过文档相关测试
  if(NOT BUILD_LIBCURL_DOCS)
    string(APPEND _test_flags " !documentation")
  endif()
  # 初始化依赖项为空
  set(_depends "")
  # 在 CI 环境中运行测试时，跳过遍历依赖目标，避免构建系统重复评估和构建
  # This avoids: GNU Make doing a slow re-evaluation of all targets and
  # skipping them, MSBuild doing a re-evaluation, and actually rebuilding them.
  if(NOT _targetname STREQUAL "test-ci")
    # 若不是 test-ci 目标，则将 testdeps 作为依赖项
    set(_depends "testdeps")
  endif()
  # 使用特殊的 '$TFLAGS' 占位符作为最后一个参数，该占位符会在 runtests.pl 中被环境变量内容替换
  # 这是为了绕过 CMake 的限制，因为 CMake 执行的命令无法跨平台引用环境变量
  # 将测试标志字符串按空格分割成列表
  string(REPLACE " " ";" _test_flags_list "${_test_flags}")
  # 创建自定义目标
  add_custom_target(${_targetname}
    # 执行的命令，使用 Perl 解释器运行 runtests.pl 脚本，并传递测试标志和 '$TFLAGS' 占位符
    COMMAND
      "${PERL_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/runtests.pl"
      ${_test_flags_list}
      "\$TFLAGS"
    # 设置依赖项
    DEPENDS "${_depends}"
    # 确保命令参数按原样传递
    VERBATIM
    # 在终端中执行该命令
    USES_TERMINAL
  )
endfunction()

# 定义一个函数，用于添加 Python 测试的自定义目标
function(curl_add_pytests _targetname _test_flags)
  # 初始化依赖项为空
  set(_depends "")
  # 若不是 pytest-ci 目标，则将 test-http-clients 作为依赖项
  if(NOT _targetname STREQUAL "pytest-ci")
    set(_depends "test-http-clients")
  endif()
  # 将测试标志字符串按空格分割成列表
  string(REPLACE " " ";" _test_flags_list "${_test_flags}")
  # 创建自定义目标
  add_custom_target(${_targetname}
    # 执行的命令，使用 pytest 运行 http 目录下的测试，并传递测试标志
    COMMAND pytest ${_test_flags_list} "${CMAKE_CURRENT_SOURCE_DIR}/http"
    # 设置依赖项
    DEPENDS "${_depends}"
    # 确保命令参数按原样传递
    VERBATIM
    # 在终端中执行该命令
    USES_TERMINAL
  )
endfunction()

# 创建 configurehelp.pm 文件，供需要运行 C 预处理器的测试使用
# 若使用 MSVC、GNU 或 Clang 编译器
if(MSVC OR CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang")
  # 设置 C 预处理器命令为编译器的 -E 选项
  set(CURL_CPP "\"${CMAKE_C_COMPILER}\" -E")
  # 若在苹果系统上且设置了 OSX 系统根目录，则添加 -isysroot 参数
  if(APPLE AND CMAKE_OSX_SYSROOT)
    string(APPEND CURL_CPP " -isysroot ${CMAKE_OSX_SYSROOT}")
  endif()
  # 添加头文件目录，类似 autotools 构建方式
  get_property(_include_dirs TARGET ${LIB_SELECTED} PROPERTY INCLUDE_DIRECTORIES)
  foreach(_include_dir IN LISTS _include_dirs)
    string(APPEND CURL_CPP " -I${_include_dir}")
  endforeach()
else()
  # 若使用其他编译器，设置 C 预处理器命令为 cpp
  set(CURL_CPP "cpp")
endif()
# 根据 configurehelp.pm.in 模板文件生成 configurehelp.pm 文件，将 CURL_CPP 变量的值填充进去
# Generate version script for the linker, for versioned symbols.
# Consumed variable:
#   CURL_CPP
configure_file(
  "${CMAKE_CURRENT_SOURCE_DIR}/configurehelp.pm.in"
  "${CMAKE_CURRENT_BINARY_DIR}/configurehelp.pm" @ONLY)

# 添加不同类型的运行测试目标
curl_add_runtests(test-quiet     "-a -s")
curl_add_runtests(test-am        "-a -am")
curl_add_runtests(test-full      "-a -p -r")
# ~flaky 表示忽略使用 flaky 关键字的测试结果
curl_add_runtests(test-nonflaky  "-a -p ~flaky ~timing-dependent")
curl_add_runtests(test-ci        "-a -p ~flaky ~timing-dependent -r -j20")
curl_add_runtests(test-torture   "-a -t -j20")
curl_add_runtests(test-event     "-a -e")

# 添加不同类型的 Python 测试目标
curl_add_pytests(curl-pytest      "")
curl_add_pytests(curl-pytest-ci   "-v")
